home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld: Complete Mac Interactive
/
Macworld Complete Mac Interactive CD)(1994).iso
/
The Best of BMUG
/
Utilities
/
Text and Speech
/
Alpha.5.76
/
Tcl
/
SystemCode
/
vi.tcl
< prev
next >
Wrap
Text File
|
1994-03-08
|
19KB
|
722 lines
# Alpha 5.x Init File
# ****************************************************************************
# FILE: vi.tcl Version 1.0
# CONTENTS: Alpha tcl startup for simple "vi" emulation.
# USAGE:
# REVISION HISTORY: 10/03/93:1:26AM PHM V1.0 created
# DESIGN NOTES:
# TODO:
# SEE ALSO: AlphaBits.tcl, procs.tcl, vi.tcl
# ***************************************************************************
# AUTHOR: Peter H. Mills (phm@cs.duke.edu)
# COPYRIGHT:
# Copyright © 1993 by Peter H. Mills
# All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that the above copyright notice and this paragraph are
# duplicated in all such forms and that any documentation,
# advertising materials, and other materials related to such
# distribution and use acknowledge that the software was developed
# by Peter H. Mills.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
# ***************************************************************************
# ==========================================
# ==== Vi MODE (Vi, Insert, Ex) ====
# ==========================================
# Vi Mode:
# Variables
# Functions: Edit
# Functions: Mode
# Key Bindings: Vi, Insert, Ex Modes
#===========================================
# ******************************************************************************
# VI (visual editor --- minimal subset) --- New section by Peter Mills
#
# ALPHA (EMACS):
# SELECTION = <curPos,selEnd> = markHilite(REGION=(Mark,Insertion_point))
# Option-cut works on Selected (alpha functions work on Regions).
# Alpha: multiple mark/clipboards, bindings, macros/built-funcs,
# reflective load, mouse ops <-> keys.
# MODE FEATURES (like unix "vi"):
# i<...> for insert mode, ESC to get back to vi mode.
# : for ex mode, RET to get back to vi mode.
# INSERT mode: type normally until ESC (DEL=erase, CR=newline).
# Inserted text saved in "viInsertText" clipboard upon ESC.
# WARNING: insert mode not reset current mark.
# VI mode:
# MOTION: h,j,k,l,0,$, DEL (backward), CR (nextline),
# ^f (nextPage), ^b (backPage), w,b,e, z ^1 (home) ^$ (lastline)
# INSERT MODE: c<w,$> i a A o O s
# EDIT TEXT: d<w,$,d,L> x J ("r" == s) d<R=rest,B=before>
# MARKS and SELECTION: m (mark) ' (goto mark)
# NEW: ^m,ESC (set current mark) ^' (exchangePointAndMark)
# O^h (highlight region<mark,pointer>)
# ^s : Selection <--> Region marked by <a,b>
# CUT and PASTE: p (yank) dx (cut) dc (copy) dv (paste) (maybe ^?)
# SEARCH: / (forward) ? (backward) n (find next)
# ^% (balance [matchbrace?])
# REDO COMMAND: . (ONLY "d" and insert-ops <c,i,A,o>)
# NEW: Will Redo last command above, ignores intervening history.
# UNDO: u (history)
# STATUS: ^g
# EX mode:
# MOTION: 1 (home) $ (end) g (goto line)
# CUT and PASTE: x (cut) c (copy) v (paste)
# Named clipboards: X (cut) C (copy) V (paste)
# Region marked by <a,b>: i (copy->insertion) m (move->insertion)
# FILE and WINDOW: q (quit) r (read) w (save)
# n (new win) s (save As) S (save selection) p (copy sel to new wind)
# MODE SWITCH commands: ^z (switch from setViModeOff<-->setviModeOn)
# MENU: setViModeOff <---> setViMode
# setViMoveOff (DEL,CR edit), setViMode
# BUFFERS: viIns (inserted) viTmp (mark)
# PROBLEMS: r needs ESC; x not backwards at eol; p above line; fillcol unset
# FUTURE: use "unbind", search needs wrap_around flag, forwardWord recog()
# EXTENSIONS: binding-modes; macro-conditional/lisp; alias-functions (r);
# load/edit from clip; named-clip<->clip; fix:macros-windows.
# SEE ALSO: emacs/epoch(X->mouse).
# ASIDE: Mac user interface Open "Look and Feel" Keyboard Shortcuts (CR,ESC).
# ******************************************************************************
# ==========================
# ==== VARIABLES ====
# ==========================
# ==== Constants ====
set esc 0x35
set del 0x33
set cr 0x24
set spc 0x31
set quot 0x27
if {! [info exists altesc]} { set altesc 0x35 }
# ==== Redo History ====
set viLastCmd ""
set viInsertText ""
# ==== Search Params ====
set searchStr ""
set searchWrap 1
set forward 1
set regExpr 1
set ignoreCase 1
set matchWords 0
# ==========================
# ==== EDIT FUNCTIONS (WORD MOTION)
# ==========================
set viWordBreak {(([a-zA-Z0-9_]+)|([!-/:-@\[-^\`\{-~]+))}
set viWordBreakPreface {([^a-zA-Z0-9_])}
set viSWordBreakPreface \
{(([^a-zA-Z0-9_]([a-zA-Z0-9_]+))|([^!-/:-@\[-^\`\{-~]([!-/:-@\[-^\`\{-~]+)))}
set viNonWhiteSpace {[!-~]}
proc viEndOfWord {} {
global viWordBreak
# # if {($start < [maxPos])} { incr start }
set retval [search -f 1 -n "$viWordBreak" [getPos]]
if {($retval != "")} {
set retval [lindex $retval 1]
goto $retval }
}
# # beginningOfWord
proc viBackwardWord {} {
global viSWordBreakPreface
set start [getPos]
if {($start > 1)} { incr start -2 }
set retval [search -f 0 -n "$viSWordBreakPreface" $start]
if {($retval != "")} {
set retval [lindex $retval 0]
goto $retval
forwardChar }
}
proc viForwardWord {} {
# # actually beginningOfWord, endOfWord below
# # forwardChar ; backwardWord ; forwardWord ; forwardWord ; backwardWord
global viSWordBreakPreface
set retval [search -f 1 -n "$viSWordBreakPreface" [getPos]]
if {($retval != "")} {
set retval [lindex $retval 0]
goto $retval
forwardChar }
}
# ==========================
# ==== EDIT FUNCTIONS ====
# ==========================
proc viDeleteCharX {} {
set start [getPos]
set point_max [maxPos]
if {($start >= $point_max) || ([lookAt [getPos]] == "\n") ||
([lookAt [getPos]] == "\r")} { backwardChar }
deleteChar
}
# # backSpace
proc viDeleteCharB {} {
backwardChar
deleteChar
}
proc viDeleteCharSel {} {
if {[getPos] == [selEnd]} {
backwardChar
deleteChar
} else { deleteText [getPos] [selEnd] }
}
proc viTypeSpace {} {
insertText " "
}
# PROBLEM: now works well only on delete line
proc viYank {} {
global viLastCmd
set viLastCmd viYank
endOfLine
yank
beginningOfLine
}
proc viJoinLine {} {
global viLastCmd
global viNonWhiteSpace
set viLastCmd viJoinLine
createTMark "viTmp" [getPos]
endOfLine
deleteChar
# # STRIP WHITE SPACE
set start [getPos]
set retval [search -f 1 -n "$viNonWhiteSpace" $start]
if {($retval != "")} { set retval [lindex $retval 0]
} else { set retval $start }
if {$start < $retval} { deleteText $start $retval }
#
insertText " "
gotoTMark "viTmp"
removeTMark "viTmp"
}
proc viOpenLine {} {
global viLastCmd
set viLastCmd viOpenLine
endOfLine
carriageReturn
viInsertMode
}
proc viOpenLineB {} {
openLine
viInsertMode
}
proc viDeleteLineEnd {} {
global viLastCmd
set viLastCmd viDeleteLineEnd
set start [getPos]
endOfLine
deleteText $start [getPos]
}
proc viDeleteLine {} {
global viLastCmd
set viLastCmd viDeleteLine
# # nextLineStart [getPos], lineStart [getPos]
endOfLine
set end [getPos]
previousLine
endOfLine
deleteText [getPos] $end
beginningOfLine
nextLine
}
proc viDeletePage {} {
global viLastCmd
set viLastCmd viDeletePage
set start [getPos]
pageForward
moveInsertionHere
deleteText $start [getPos]
}
proc viDeleteRest {} {
global viLastCmd
set viLastCmd ""
set start [getPos]
endOfBuffer
deleteText $start [getPos]
}
proc viDeleteAllBefore {} {
global viLastCmd
set viLastCmd ""
set end [getPos]
beginningOfBuffer
deleteText [getPos] $end
}
proc viDeleteWord {} {
global viLastCmd
set viLastCmd viDeleteWord
set start [getPos]
viForwardWord
set end [getPos]
if {$start < $end} { deleteText $start $end }
}
proc viAdd {} {
global viLastCmd
set viLastCmd viAdd
viForwardWord
viInsertMode
}
proc viAddEnd {} {
global viLastCmd
set viLastCmd viAddEnd
endOfLine
viInsertMode
}
proc viChangeLine {} {
global viLastCmd
set viLastCmd viChangeLine
set start [getPos]
endOfLine
# # deleteText $start [getPos] ; endOfLine
select $start [getPos]
viInsertMode
}
proc viChangeWord {} {
global viLastCmd
set viLastCmd viChangeWord
set start [getPos]
viEndOfWord
# # deleteText $start [getPos] (deleteWord)
select $start [getPos]
viInsertMode
}
proc viSubChar {} {
global viLastCmd
set viLastCmd viSubChar
set start [getPos]
# # deleteChar
set end $start
incr end
select $start $end
viInsertMode
}
# Search with Wrap (searchWrap) ;
# Max_Position(File) = {0,[maxPos]-1}
proc viSearch {} {
global searchStr
global searchWrap
global forward
set start [getPos]
set point_max [expr {[maxPos] - 1}]
if {$forward} { if {($start < $point_max)} { incr start }
} else { if {$start > 0} { incr start -1 } }
set retval [search -f $forward -n "$searchStr" $start]
if {($retval == "") && $searchWrap} {
if {$forward} { set frompos 0 } else { set frompos $point_max }
if {$forward} {
set retval [search -f $forward -n "$searchStr" -l $start $frompos]
} else {
set retval [search -f $forward -n "$searchStr" $frompos]
if {($retval != "") && ([lindex $retval 0] < $start)} {
set retval ""} }
}
if {$retval == ""} { beep } else { goto [lindex $retval 0] }
}
proc viSearchBackward {} {
global searchStr
global forward
if [catch { prompt "Search for: " $searchStr } retval] { return }
set forward 0
set searchStr $retval
viSearch
}
proc viSearchForward {} {
global searchStr
global forward
# # set retval [getline "Search for: " $searchStr] ;
# # if {"" == $retval} { return }
if [catch { prompt "Search for: " $searchStr } retval] { return }
set forward 1
set searchStr $retval
viSearch
}
proc viRedoSearch {} {
global forward
if {$forward} { repeatSearchForward } else { repeatSearchBackward }
}
# ===========================================================================
# tabsToPrint : ^I->\^I ; \TAB->\ ^I ; TAB->^I
# printToTabs : ^i->^I ; \^I->^i ; ^I->TAB ; ^i->^I
# ===========================================================================
proc viCopySelWind {} {
if {[getPos] == [selEnd]} { return }
set text [getText [getPos] [selEnd]]
new
moveInsertionHere
insertText $text
}
# (view named clipboard, copy and view clipboard)
# ==== save selection to file ====
proc viSaveSelection {} {
viCopySelWind
saveAs
killWindow
}
# ==== SAVED REGION[Mark,insert] <=> SELECTION(curPos<selEnd) ====
proc viRegionAB {} {
set pos [getPos]
if {[catch { gotoTMark "a" }]} { beep ; return "" }
set start [getPos]
if {[catch { gotoTMark "b" }]} { beep ; goto $pos ; return "" }
set end [getPos]
goto $pos
if {$start > $end} { set temp $start ; set start $end ; set end $temp }
if {$start <= $end} { return "" }
return [list $start $end]
}
proc viSelectToSaved {} {
# if {[getSelect] == ""} {}
if {[getPos] == [selEnd]} {
set retval [viRegionAB]
if {$retval == ""} { return }
set start [lindex $retval 0] ; set end [lindex $retval 1]
select $start $end
removeTMark "a"
removeTMark "b"
} else {
createTMark "a" [getPos]
createTMark "b" [selEnd]
# markHilite -VS- select [getPos] [getPos]
}
}
#
# NOTE: like drag-and-drop moving (vs. active objects)
#
# ==== Copy region marked by "a"-"b" to curPos
proc viCopyAB {{kill 0}} {
set retval [viRegionAB]
if {$retval == ""} { return }
set start [lindex $retval 0] ; set end [lindex $retval 1]
set text [getText $start $end]
if {$kill} { deleteText $start $end }
if {[getPos] == [selEnd]} { insertText $text
} else { replaceText [getPos] [selEnd] $text }
}
proc viMoveAB {} { viCopyAB 1 }
# =====================================================================
# ==========================
# ==== MODE FUNCTIONS ====
# ==========================
# ==== SUBMODE (Minor Mode)
#
# WARNING: viSubMode, viInsertText should be BUFFER LOCAL (curWinId)
#
# "subMode" from procs.tcl, *is* buffer local -- changeSubMode().
#
# ==== SWITCH to VI Command Mode ====
proc viCmdMode {} { changeSubMode "Vi" }
# changeMode: restores mode-local params, sets 1st time to TextModeParams
proc setViMode {} {
changeMode "Vi"
uplevel #0 {
set wordBreak "$viWordBreak"
set wordBreakPreface "$viWordBreakPreface"
}
viCmdMode
}
proc setViModeOff {} {
message "Exiting vi mode"
changeMode "Text"
# # bind 'z' <z> setViMode
}
proc viRedoLastCmd {} {
global viLastCmd
global subMode
if {$viLastCmd == ""} {
abortEm
return
}
set subMode "Vi"
$viLastCmd
if {$subMode == "Insert"} { viRedoInsert }
}
# ==== SWITCH to VI Insert Mode ====
proc viInsertCmd {} {
global viLastCmd
#==== changeSubMode "Insert"
global subMode
global curWinId
global winNumToSubMode
set subMode "Insert"
displayMode $subMode
if {$curWinId >= 0} { set winNumToSubMode($curWinId) $subMode }
#====
set viLastCmd viInsertCmd
if {[getPos] != [selEnd]} { deleteText [getPos] [selEnd] }
createTMark "viIns$curWinId" [getPos]
}
proc viInsertMode {} {
#==== changeSubMode "Insert"
global subMode
global curWinId
global winNumToSubMode
set subMode "Insert"
displayMode $subMode
if {$curWinId >= 0} { set winNumToSubMode($curWinId) $subMode }
#====
createTMark "viIns$curWinId" [getPos]
}
# END INSERT: save inserted text in insert-buffer, switch to VI Command Mode.
# PROBLEM: "viIns" mark may be gone via deletion past insert-point (~bind redo)
proc viEndInsMode {} {
global viInsertText
#==== changeSubMode "Vi" (viCmdMode)
global subMode
global curWinId
global winNumToSubMode
set subMode "Vi"
displayMode $subMode
if {$curWinId >= 0} { set winNumToSubMode($curWinId) $subMode }
#====
set end [getPos]
if [catch { gotoTMark "viIns$curWinId" }] { beep ; return }
# # removeTMark "viIns$curWinId" --- auto at win close
set start [getPos]
goto $end
if {$start >= $end} { return }
set viInsertText [getText $start $end]
}
proc viRedoInsert {} {
global viInsertText
if {[getPos] == [selEnd]} { insertText $viInsertText
} else { replaceText [getPos] [selEnd] $viInsertText }
viCmdMode
}
# ==== SWITCH to vi EX Mode ====
proc viExMode {} {
changeSubMode "Ex"
message "ex Mode"
}
# ==========================
# ==== KEY BINDINGS ====
# ==========================
# ==== BINDINGS for EMACS (deleted from original) ====
# bind 'j' <e> fillRegion
# bind 'p' <e> fillParagraph
# bind '<' <se> beginningOfBuffer
# bind '>' <se> endOfBuffer
bind 'z' <z> setViMode
# ==================================
# ==== INSERT MODE BINDINGS ====
# ==================================
# NOTE: "bind" to no arg will unbind (to self-insert), should have lastChar var.
bind $esc viEndInsMode "Insert"
bind $altesc viEndInsMode "Insert"
bind $del viDeleteCharSel "Insert"
bind $del <s> viDeleteCharSel "Insert"
bind '\n' carriageReturn "Insert"
bind '\n' <s> carriageReturn "Insert"
bind '\r' carriageReturn "Insert"
bind '\r' <s> carriageReturn "Insert"
bind $spc viTypeSpace "Insert"
bind $spc <s> viTypeSpace "Insert"
bind 'z' <z> setViModeOff "Insert"
# ==========================
# ==== VI MODE BINDINGS ====
# ==========================
# ESC==abort (reset so not void redo "viIns"), ' '==special
# DEL==backwardChar (vs. backSpace)
bind $esc abortEm "Vi"
bind $altesc abortEm "Vi"
bind $del viDeleteCharSel "Vi"
bind $del <s> viDeleteCharSel "Vi"
bind '\n' nextLine "Vi"
bind '\n' <s> nextLine "Vi"
bind '\r' nextLine "Vi"
bind '\r' <s> nextLine "Vi"
bind $spc forwardChar "Vi"
bind $spc <s> forwardChar "Vi"
bind 'i' viInsertCmd "Vi"
bind ':' <s> viExMode "Vi"
bind 'z' <z> setViModeOff "Vi"
bind '\' startEscape "Vi"
bind '\' <e> evalCommand "Vi"
bind 'a' viAdd "Vi"
bind 'a' <s> viAddEnd "Vi"
bind 'b' viBackwardWord "Vi"
bind 'c' prefixChar "Vi"
bind 'd' prefixChar "Vi"
bind 'e' viEndOfWord "Vi"
bind 'g' currentPosition "Vi"
bind 'h' backwardChar "Vi"
bind 'j' nextLine "Vi"
bind 'j' <s> viJoinLine "Vi"
bind 'k' previousLine "Vi"
bind 'l' forwardChar "Vi"
bind 'm' setNamedMark "Vi"
bind 'n' viSearch "Vi"
bind 'o' viOpenLine "Vi"
bind 'o' <s> viOpenLineB "Vi"
bind 'p' viYank "Vi"
bind 'r' viSubChar "Vi"
bind 's' viSubChar "Vi"
bind 't' viEndOfWord "Vi"
bind 'u' undo "Vi"
bind 'v' viBackwardWord "Vi"
bind 'w' viForwardWord "Vi"
bind 'x' viDeleteCharX "Vi"
bind 'y' yank "Vi"
bind 'z' insertToTop "Vi"
bind '0' beginningOfLine "Vi"
bind '%' <s> balance "Vi"
bind '$' <s> endOfLine "Vi"
bind $quot gotoMark "Vi"
bind '/' viSearchForward "Vi"
bind '?' <s> viSearchBackward "Vi"
# ' marks (^' for '')
# m: named mark (^m for set current mark)
# n: repeatSearchForward (redo commands (persistent))
# d: <x> w or $
# c: <e> w or $
# ==================================================================
# ==== VI MODE BINDINGS -- PERMANENT (prefixed) SETTINGS ====
# ==================================================================
bind 'a' <z> beginningOfLine "Vi"
bind 'b' <z> pageBack "Vi"
bind 'e' <z> endOfLine "Vi"
bind 'f' <z> pageForward "Vi"
bind 'g' <z> currentPosition "Vi"
bind 'h' <z> backwardChar "Vi"
bind 'j' <z> nextLine "Vi"
bind 'k' <z> previousLine "Vi"
bind 'l' <z> forwardChar "Vi"
bind 'n' <z> scrollDownLine "Vi"
bind 'p' <z> scrollUpLine "Vi"
bind 'q' <z> keyAscii "Vi"
bind 'r' <z> fillParagraph "Vi"
bind 's' <z> viSelectToSaved "Vi"
# REGION SELECT/EDIT
bind 't' <z> viEndOfWord "Vi"
bind 'u' <z> undo "Vi"
bind 'v' <z> viBackwardWord "Vi"
bind 'w' <z> viForwardWord "Vi"
bind 'y' <z> viYank "Vi"
bind '1' <z> beginningOfBuffer "Vi"
bind '4' <z> endOfBuffer "Vi"
bind '5' <z> balance "Vi"
bind '.' viRedoLastCmd "Vi"
# . : redo command (history sensitive)
# ==== DELETE MODE MODIFIERS (d prefix)
bind 'd' <z> prefixChar "Vi"
bind 'x' <D> cut "Vi"
bind 'c' <D> copy "Vi"
bind 'v' <D> paste "Vi"
bind 'w' <D> viDeleteWord "Vi"
bind 'd' <D> viDeleteLine "Vi"
bind '$' <sD> viDeleteLineEnd "Vi"
bind 'L' <sD> viDeletePage "Vi"
bind 'R' <sD> viDeleteRest "Vi"
bind 'B' <sD> viDeleteAllBefore "Vi"
# ==== CHANGE MODE MODIFIERS (c prefix)
bind 'c' <z> prefixChar "Vi"
bind 'w' <C> viChangeWord "Vi"
bind '$' <Cs> viChangeLine "Vi"
# === MARK MODE MODIFIERS (^') ====
bind $quot <z> exchangePointAndMark "Vi"
bind 'm' <z> setMark "Vi"
bind '^' <z> exchangePointAndMark "Vi"
bind '@' <z> setMark "Vi"
# ==========================
# ==== EX MODE BINDINGS ====
# ==========================
bind $esc viCmdMode "Ex"
bind $altesc viCmdMode "Ex"
bind $del viDeleteCharB "Ex"
bind $del <s> viDeleteCharB "Ex"
bind '\n' viCmdMode "Ex"
bind '\n' <s> viCmdMode "Ex"
bind '\r' viCmdMode "Ex"
bind '\r' <s> viCmdMode "Ex"
bind 'z' <z> setViModeOff "Ex"
bind 'c' copy "Ex"
bind 'c' <s> copyNamedClipboard "Ex"
bind 'g' gotoLine "Ex"
bind 'i' viCopyAB "Ex"
bind 'm' viMoveAB "Ex"
bind 'n' new "Ex"
bind 'p' viCopySelWind "Ex"
bind 'q' killWindow "Ex"
bind 'r' insertFile "Ex"
bind 's' saveAs "Ex"
bind 's' <s> viSaveSelection "Ex"
bind 'v' paste "Ex"
bind 'v' <s> pasteNamedClipboard "Ex"
bind 'w' save "Ex"
bind 'x' cut "Ex"
bind 'x' <s> cutNamedClipboard "Ex"
bind '1' beginningOfBuffer "Ex"
bind '$' <s> endOfBuffer "Ex"
# ***************************************************************************
# END of VI section.
# ***************************************************************************
#===================================
# ==== EMACS MODE BINDINGS ====
#===================================
#======================== END NUMLINES 672 ====================================